/* 
 * File:   SVMScaler.h
 * Author: kiennd
 *
 * Created on December 27, 2013, 3:02 PM
 * 
 * C++ wrapper for svmscale.h
 * 
 * NOTE: This is NOT thread-safe
 * 
 * USAGE: 
 *	Initialize scaler with appropriate parameters and then run scaling.
 * 
 *	When we run scaling file (after initializing), remain parameters are loaded
 * from provided files. 
 * 
 *	When we just scale one data point(after initializing), 
 * make sure that feature vectors, yMax, yMin, maxIndex, minIndex are set to 
 * appropriate values; otherwise, they take default values: 
 * 0..0, 0..0, -DBL_MAX, DBL_MAX, 0, 1. 
 * 
 * 
 * 
 * NOTE: We can load all parameters in restore file with restore() method 
 * and don't need to initialize anything.
 * 
 */

#ifndef SVMSCALER_H
#define	SVMSCALER_H

#include <cstdio>

#include <vector>
#include <string>

using namespace std;

class SVMScaler {
private:
	const static int kDefaultMaxLineLen = 1024;
	long int numNonZeros;
	long int numNonZerosNew;

public:

	vector<double> featureMax;
	vector<double> featureMin;
	double yMax;
	double yMin;
	int maxIndex;
	int minIndex;

	double lower;
	double upper;

	bool isYScaling;
	double yLower;
	double yUpper;

	SVMScaler();

	/**
	 * Initialize scaler with specific values
     * @param lower lower value
     * @param upper upper value
     * @param isYScaling whether to scale label (y) or not
     * @param yLower label lower if scale label
     * @param yUpper label upper if scale label
     */
	void initialize(double lower,
			double upper,
			bool isYScaling,
			double yLower,
			double yUpper);
	
	/**
	 * Restore parameters from restore file.
     */
	void restore(const char* fileName);
	
	/**
	 * Parse data in a input line
	 */
	void parseData(const string& line, double& y, vector<int>& indices, vector<double>& values);
	
	/**
	 * Scale data
     */
	void scaleData(double y, vector<int> indices, vector<double> values,
		double& scaledY, vector<int>& scaledIndices, vector<double>& scaledValues);
	
	/**
	 * Scale data, right in the provided containers
     */
	void scaleData(double& y, vector<int>& indices, vector<double>& values);
	

	/**
	 * Data scaling
	 * 
	 * @param outFileName output file name
	 * @param inFileName input file name (data file name)
	 * @param isSaveParameter whether to save scaling parameter or not
	 * @param saveFileName scaling parameter saving file name
	 * @param isRestoreParameter whether to restore scaling parameter or not
	 * @param restoreFileName scaling parameter restoring file name
	 */
	void scaleFile(const char *outFileName,
			const char *inFileName,
			bool isSaveParameter,
			const char *saveFileName,
			bool isRestoreParameter,
			const char * restoreFileName);

private:

	void outputY(FILE *f, double value);
	void outputX(FILE *f, int index, double value);
	
	/**
	 * Restore max/min index from file
     */
	void restoreMaxMinIndex(const char* fileName);
	
	/**
	 * Restore x, y, and feature max/min from file
     */
	void restoreXYAndFeatures(const char* fileName);
	
	/**
	 * Find max/min index in restore file, if any, 
	 * and then find in input file
     */
	void findMaxMinIndex(const char * filename,
		bool isRestoreParameter,
		const char * restoreFileName);
	
	/**
	 * Find min/max feature values in input file
     */
	void findMaxMinValues(const char * filename);
	
	/**
	 * Save parameters to file
     */
	void saveParameters(const char * save_filename);
	
	/**
	 * Scale target Y
     */
	double scaleY(double value);
	
	/**
	 * Scale value of feature index-th
     */
	double scaleX(int index, double value);
};

#endif	/* SVMSCALER_H */

